﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;


using Crystalbyte.Equinox;
using Crystalbyte.Equinox.Imap;
using Crystalbyte.Equinox.Security;
using Crystalbyte.Equinox.Security.Authentication;

using GmailFetcher.Models;

namespace GmailFetcher.Crawler
{
    public class EmailCrawler
    {
        private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

        private EmailAccount _emailAcc;

        public EmailCrawler(EmailAccount acc)
        {
            _emailAcc = acc;
        }
        public static Object  kickOffCrawling(EmailAccount account)
        {
            Object  returnObject = null;
            if (account.type == EmailAccount.IMAP)
            {
                EmailCrawler     imapCrawler = new EmailCrawler(account);
                EmailCrawledData crawledEmailData = imapCrawler.CrawlAndProcessIMAPEmails(account.EmailFolder);
                returnObject = crawledEmailData as Object;
            }


            return returnObject ;
        }


        #region  PROCESSING_STARTS

        private EmailCrawledData CrawlAndProcessIMAPEmails(string folder)
        {
            ImapClient emailClient = new ImapClient();
            EmailCrawledData crawledEmailData = new EmailCrawledData();

            if (emailClient == null)
            {
                log.FatalFormat("Unable to Create Instance of IMAP Client for {0} ", _emailAcc.host);
                return null;
            }
            emailClient.Security = SecurityPolicies.Explicit;
            // Connect Now 

            emailClient.Connect(_emailAcc.host, ImapPorts.Ssl);
            if (!emailClient.IsConnected)
            {
                log.FatalFormat("Unable to Connect to  {0} ", _emailAcc.host);
                return null;
            }

            NetworkCredential nwCreds = new NetworkCredential(_emailAcc.userName, _emailAcc.passwd);
            emailClient.Authenticate(nwCreds, SaslMechanics.Login);
            if (!emailClient.IsAuthenticated)
            {
                log.FatalFormat("Unable to Authenticate  to  {0}  and {1} ", _emailAcc.host, _emailAcc.userName);
                return null;
            }

            //Crawl Thru InBox 

            emailClient.Select(folder);

            var query = emailClient.Messages.Where(i => i.Date > DateTime.Today.AddDays(-20) && !i.Flags.HasFlag(MessageFlags.Seen)).Select(i => new EmailMessage { Envelope = i.Envelope, Uid = i.Uid, BodyStructure = i.BodyStructure, Flags = i.Flags, Text = i.Text });

            // Messages 
            //var query = from i in emailClient.Messages where i.SequenceNumber > 0 select new EmailMessage { Envelope = i.Envelope, Uid = i.Uid, BodyStructure = i.BodyStructure, Flags=i.Flags};



            /*
             *
             * var htmlViewInfo = bodyStructure.Views.Where(x => x.MediaType == "text/html");
               var htmlView = client.FetchView(htmlViewInfo);

               // fetching the third attachment
               var thirdAttachmentInfo = bodyStructure.Attachments.ElementAt(2);
               var thirdAttachment = client.FetchAttachment(thirdAttachmentInfo);

               // fetching only images
               var imageInfos = bodyStructure.Attachments.Where(x => x.MediaType.StartsWith("image"));
               var images = imageInfos.Select(client.FetchAttachment).ToList();

               // fetching only images with a size smaller than 100k (encoded)
               var imageInfos = bodyStructure.Attachments.Where(x => 
                x.MediaType.StartsWith("image") && x.SizeEncoded.MegaBytes < 0.1);
               var images = imageInfos.Select(client.FetchAttachment).ToList();
             * 
             */


            foreach (EmailMessage  emailItem in query)
            {
                log.DebugFormat(" Mesasage : {0} : {1} : {2} : {3} ", emailItem.Flags, emailItem.Envelope.Subject, emailItem.Uid, emailItem.Text);
                crawledEmailData._emailList.Add(emailItem);
            }

            //Log Out 
            emailClient.Logout();
            //Disconnect at the end
            emailClient.Disconnect();
            return crawledEmailData;
        }

        #endregion

    }
}
